FinTech Homework

Roger Jang


Due date: 2023/10/15 23:59:59

Trading Strategies Using Technical Indicators

Important info for all homework

In this homework, you need to design a trading strategy to maximize the return of stock trading over a future period of time.

Your design flowchart should be like this:
  1. Determine the technical indicator (TI) you want to use. (You can use more than one TIs.)
  2. Define the trading strategy using the TIs, with some modifiable parameters for optimizing the return.
  3. Optimzie the return using the historical price data.
  4. Use the obtained parameters for trading over a future period of time.

For instance, in the following example code, we use MA (moving average) as the TI, with the parameters of window size, alpha, beta. Then we optimize these parameters by exhaustive search, as shown in bestParamViaExhaustiveSearch.py:

import sys import numpy as np import pandas as pd # Decision of the current day by the current price, with 3 modifiable parameters def myStrategy(pastPriceVec, currentPrice, windowSize, alpha, beta): import numpy as np action=0 # action=1(buy), -1(sell), 0(hold), with 0 as the default action dataLen=len(pastPriceVec) # Length of the data vector if dataLen==0: return action # Compute ma if dataLen<windowSize: ma=np.mean(pastPriceVec) # If given price vector is small than windowSize, compute MA by taking the average else: windowedData=pastPriceVec[-windowSize:] # Compute the normal MA using windowSize ma=np.mean(windowedData) # Determine action if (currentPrice-ma)>alpha: # If price-ma > alpha ==> buy action=1 elif (currentPrice-ma)<-beta: # If price-ma < -beta ==> sell action=-1 return action # Compute return rate over a given price vector, with 3 modifiable parameters def computeReturnRate(priceVec, windowSize, alpha, beta): capital=1000 # Initial available capital capitalOrig=capital # original capital dataCount=len(priceVec) # day size suggestedAction=np.zeros((dataCount,1)) # Vec of suggested actions stockHolding=np.zeros((dataCount,1)) # Vec of stock holdings total=np.zeros((dataCount,1)) # Vec of total asset realAction=np.zeros((dataCount,1)) # Real action, which might be different from suggested action. For instance, when the suggested action is 1 (buy) but you don't have any capital, then the real action is 0 (hold, or do nothing). # Run through each day for ic in range(dataCount): currentPrice=priceVec[ic] # current price suggestedAction[ic]=myStrategy(priceVec[0:ic], currentPrice, windowSize, alpha, beta) # Obtain the suggested action # get real action by suggested action if ic>0: stockHolding[ic]=stockHolding[ic-1] # The stock holding from the previous day if suggestedAction[ic]==1: # Suggested action is "buy" if stockHolding[ic]==0: # "buy" only if you don't have stock holding stockHolding[ic]=capital/currentPrice # Buy stock using cash capital=0 # Cash realAction[ic]=1 elif suggestedAction[ic]==-1: # Suggested action is "sell" if stockHolding[ic]>0: # "sell" only if you have stock holding capital=stockHolding[ic]*currentPrice # Sell stock to have cash stockHolding[ic]=0 # Stocking holding realAction[ic]=-1 elif suggestedAction[ic]==0: # No action realAction[ic]=0 else: assert False total[ic]=capital+stockHolding[ic]*currentPrice # Total asset, including stock holding and cash returnRate=(total[-1]-capitalOrig)/capitalOrig # Return rate of this run return returnRate if __name__=='__main__': returnRateBest=-1.00 # Initial best return rate df=pd.read_csv(sys.argv[1]) # read stock file adjClose=df["Adj Close"].values # get adj close as the price vector windowSizeMin=11; windowSizeMax=20; # Range of windowSize to explore alphaMin=-5; alphaMax=5; # Range of alpha to explore betaMin=-5; betaMax=5 # Range of beta to explore # Start exhaustive search for windowSize in range(windowSizeMin, windowSizeMax+1): # For-loop for windowSize print("windowSize=%d" %(windowSize)) for alpha in range(alphaMin, alphaMax+1): # For-loop for alpha print("\talpha=%d" %(alpha)) for beta in range(betaMin, betaMax+1): # For-loop for beta print("\t\tbeta=%d" %(beta), end="") # No newline returnRate=computeReturnRate(adjClose, windowSize, alpha, beta) # Start the whole run with the given parameters print(" ==> returnRate=%f " %(returnRate)) if returnRate > returnRateBest: # Keep the best parameters windowSizeBest=windowSize alphaBest=alpha betaBest=beta returnRateBest=returnRate print("Best settings: windowSize=%d, alpha=%d, beta=%d ==> returnRate=%f" %(windowSizeBest,alphaBest,betaBest,returnRateBest)) # Print the best result You can run the above program on "0050.TW-short.csv" by typing "python bestParamByExhaustiveSearch.py 0050.TW-short.csv" to obtain the best return rate: Best settings: windowSize=14, alpha=0, beta=-5 ==> returnRate=0.815243 Therefore you can use these parameter values in the program "myStrategy.py", as follows def myStrategy(pastPriceVec, currentPrice): # Explanation of my approach: # 1. Technical indicator used: MA # 2. if price-ma>alpha ==> buy # if price-ma<-beta ==> sell # 3. Modifiable parameters: alpha, beta, and window size for MA # 4. Use exhaustive search to obtain these parameter values (as shown in bestParamByExhaustiveSearch.py) import numpy as np # Set best parameters windowSize=14 alpha=0 beta=-5 action=0 # action=1(buy), -1(sell), 0(hold), with 0 as the default action dataLen=len(pastPriceVec) # Length of the data vector if dataLen==0: return action # Compute MA if dataLen<windowSize: ma=np.mean(pastPriceVec) # If given price vector is small than windowSize, compute MA by taking the average else: windowedData=pastPriceVec[-windowSize:] # Compute the normal MA using windowSize ma=np.mean(windowedData) # Determine action if (currentPrice-ma)>alpha: # If price-ma > alpha ==> buy action=1 elif (currentPrice-ma)<-beta: # If price-ma < -beta ==> sell action=-1 return action You can then try the trading strategy on "0050.TW-short.csv" by typing "python rrEstimate.py 0050.TW-short.csv" to get the result: rr=81.524342% Other notes: